package com.allen.framework.readwriterouter.properties;

import com.allen.framework.readwriterouter.datasource.DynamicDatasource;
import com.allen.framework.readwriterouter.datasource.DynamicDatasourceHolder;
import com.allen.framework.readwriterouter.enumerate.DynamicDatasourceRouterTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.datasource.DataSourceException;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.sql.DataSource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: Allen
 * @Date: Created in 10:01 2019-08-29
 * @Description:
 */
@Slf4j
@Configuration
public class DynamicDatasourceConfiguration {

    private DynamicDatasourceHolder dynamicDatasourceHolder;

    public DynamicDatasourceConfiguration(DynamicDatasourceHolder dynamicDatasourceHolder) {
        this.dynamicDatasourceHolder = dynamicDatasourceHolder;
    }

    @Bean
    public DataSource buildDynamicDatasource(DynamicDatasourceConfigurationProperties dynamicDatasourceConfigurationProperties) {

        Map<Object, Object> targetDataSources = new HashMap<Object, Object>();
        Map<String, String> masterAndSlaveDBConfigurationMap = dynamicDatasourceConfigurationProperties.getDatasource();
        if (masterAndSlaveDBConfigurationMap.keySet().size() == 0) {
            throw new DataSourceException("master and salve can not be null!");
        }
        List<String> slaveLists = new ArrayList<String>();
        String masterKey = null;
        for (String key : masterAndSlaveDBConfigurationMap.keySet()) {
            String dbConfig = masterAndSlaveDBConfigurationMap.get(key);
            DynamicDBConfiguration dynamicDBConfiguration = buildConfigObj(dbConfig);
            log.debug("load dynamic datasource {}" ,dynamicDBConfiguration);
            DataSource dataSource = DataSourceBuilder.create().url(dynamicDBConfiguration.getUrl()).username(dynamicDBConfiguration.getUsername())
                    .password(dynamicDBConfiguration.getPassword()).build();
            targetDataSources.put(key, dataSource);
            if (DynamicDatasourceRouterTypeEnum.WRITE.getCode().equals(dynamicDBConfiguration.getType())) {
                masterKey = key;
                log.debug("datasource type:{}",DynamicDatasourceRouterTypeEnum.WRITE.getDesc());
            }
            if (DynamicDatasourceRouterTypeEnum.READ.getCode().equals(dynamicDBConfiguration.getType())) {
                slaveLists.add(key);
                log.debug("datasource type:{}",DynamicDatasourceRouterTypeEnum.READ.getDesc());
            }
        }
        //如果不存在副表，则使用主表作为查询表
        if (slaveLists.size() == 0) {
            slaveLists.add(masterKey);
        }
        dynamicDatasourceHolder.setMaster(masterKey);
        dynamicDatasourceHolder.setSlaveList(slaveLists);
        DynamicDatasource myRoutingDataSource = new DynamicDatasource(dynamicDatasourceHolder);
        myRoutingDataSource.setTargetDataSources(targetDataSources);
        return myRoutingDataSource;

    }

    private DynamicDBConfiguration buildConfigObj(String dbConfig) {

        DynamicDBConfiguration dynamicDBConfiguration = new DynamicDBConfiguration();
        String[] configStrs = dbConfig.split(" ");
        for (String u : configStrs) {
            String value = u.substring(u.indexOf(":")+1).trim();
            if (u.startsWith("type")) {
                dynamicDBConfiguration.setType(value);
            } else if (u.startsWith("url")) {
                dynamicDBConfiguration.setUrl(value);
            } else if (u.startsWith("username")) {
                dynamicDBConfiguration.setUsername(value);
            } else if (u.startsWith("password")) {
                dynamicDBConfiguration.setPassword(value);
            } else {
                throw new DataSourceException("dynamic datasource configuration init failed...");
            }
        }
        return dynamicDBConfiguration;
    }


}
